package com.molichuxing.gateway.bff.stock.services.impl;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.molichuxing.framework.dto.Paged;
import com.molichuxing.framework.dto.TabDto;
import com.molichuxing.framework.exception.BizException;
import com.molichuxing.framework.utils.DateUtil;
import com.molichuxing.framework.utils.EmailUtil;
import com.molichuxing.framework.utils.ObjectCastUtil;
import com.molichuxing.gateway.bff.stock.convertor.Convert;
import com.molichuxing.gateway.bff.stock.entity.request.modify.StockCarModifyVo;
import com.molichuxing.gateway.bff.stock.entity.response.StockCarDetailVo;
import com.molichuxing.gateway.bff.stock.entity.response.StockCarStockVo;
import com.molichuxing.gateway.bff.stock.entity.response.StockCarVo;
import com.molichuxing.gateway.bff.stock.services.StockCarBffService;
import com.molichuxing.gateway.property.StockStatusEnum;
import com.molichuxing.gateway.property.StockTypeEnum;
import com.molichuxing.gateway.utils.PoiExcelUtil;
import com.molichuxing.gateway.utils.entity.UserEntity;
import com.molichuxing.services.business.dto.request.modify.StockCarBizModifyDto;
import com.molichuxing.services.business.dto.response.DealerStoreInfoBizDto;
import com.molichuxing.services.business.dto.response.StockCarBizDto;
import com.molichuxing.services.business.dto.response.StockCarDetailDto;
import com.molichuxing.services.business.dto.response.VehicleNameBizDto;
import com.molichuxing.services.business.service.OrderDealerBizService;
import com.molichuxing.services.business.service.StockCarBizService;
import com.molichuxing.services.business.service.StoreBizService;
import com.molichuxing.services.business.service.VehicleBizService;
import com.molichuxing.services.infrastructure.dto.request.create.FenceExceptionCreateDto;
import com.molichuxing.services.infrastructure.dto.request.create.IovFenceBindingCreateDto;
import com.molichuxing.services.infrastructure.dto.request.modify.IovFenceBindingModifyDto;
import com.molichuxing.services.infrastructure.dto.request.modify.OrderDealerStartStatusModifyDto;
import com.molichuxing.services.infrastructure.dto.response.CarDto;
import com.molichuxing.services.infrastructure.dto.response.EntrepotStorageDto;
import com.molichuxing.services.infrastructure.dto.response.IovFenceDto;
import com.molichuxing.services.infrastructure.dto.response.OrderDealerDetailBasicDto;
import com.molichuxing.services.infrastructure.dto.response.OwnershipDto;
import com.molichuxing.services.infrastructure.dto.response.StockCarDto;
import com.molichuxing.services.infrastructure.dto.response.StockStoreDto;
import com.molichuxing.services.infrastructure.dto.response.StoreDetailDto;
import com.molichuxing.services.infrastructure.service.CarFenceExceptionService;
import com.molichuxing.services.infrastructure.service.CarService;
import com.molichuxing.services.infrastructure.service.EnterpriseCarService;
import com.molichuxing.services.infrastructure.service.EntrepotStorageService;
import com.molichuxing.services.infrastructure.service.IovFenceService;
import com.molichuxing.services.infrastructure.service.OrderDealerDeliveryService;
import com.molichuxing.services.infrastructure.service.OwnershipService;
import com.molichuxing.services.infrastructure.service.StockCarService;
import com.molichuxing.services.infrastructure.service.StockStoreService;
import com.molichuxing.services.infrastructure.service.StoreDetailService;
import com.molichuxing.services.property.CarsOperateStatusEnum;
import com.molichuxing.services.property.DealerTypeEnum;
import com.molichuxing.services.property.OrderDealerStatusEnum;
import com.molichuxing.services.property.StockCarStatusEnum;
import com.molichuxing.services.property.StockCarStockTypeEnum;
import com.molichuxing.services.property.StockCarTypeEnum;

/**
 * 
 * @author liyg
 * 库存车辆bff服务实现类
 * 2019-08-26
 *
 */
@Service("stockCarBffService")
public class StockCarBffServiceImpl implements StockCarBffService{

	private static final Logger logger = LoggerFactory.getLogger(StockCarBffServiceImpl.class);
	
	@Resource
	private StockCarBizService stockCarBizService;
	
	@Resource
	private StockCarService stockCarService;
	
	@Resource
	private StockStoreService stockStoreService;
	
	@Resource
	private StoreBizService storeBizService;
	
	@Resource
	private VehicleBizService vehicleBizService;
	
	@Resource
	private CarService carService;
	
	@Resource
	private OwnershipService ownershipService;
	
	@Resource
	private OrderDealerBizService orderDealerBizService;
	
	@Resource
	private OrderDealerDeliveryService orderDealerDeliveryService;
	
	@Resource
	private IovFenceService iovFenceService;
	
	@Resource
	private EntrepotStorageService entrepotStorageService;
	
	@Resource
	private StoreDetailService storeDetailService;
	
	@Resource
	private CarFenceExceptionService carFenceExceptionService;
	
	@Resource
	private EnterpriseCarService enterpriseCarService;
	
	@Value("${email_account}")
	private String emailAccount;

	@Value("${email_password}")
	private String emailPassword;
	
	
	/**
	 *库存车辆列表
	 * @param map 参数
	 *key:tabType       Integer    tab类型
	 *key:vin            String    车架号 非必填
	 *key:licencePlate   String    车牌号 非必填
	 *key:operationState Integer   运营状态 非必填
	 *key:vehicleId  Integer 车型id 非必填
	 *key:type       Integer 出入库类型 非必填
	 *key:stockType       Integer 库类型（中转库或门店）非必填
	 *key:stockId    Integer 中转库id 非必填
	 *key:startTime  LocalDateTime 开始时间 非必填
	 *key:endTime    LocalDateTime 结束时间 非必填
	 *key:sortName   String 排序字段 
	 *key:sortWay    String 排序方式 
	 *key:pageNum    Integer 当前页
	 *key:pageSize   Integer 每页显示条数
	 * @return
	 * @throws Exception 
	 */
	@Override
	public Paged<StockCarVo> getStockCarList(Map<String, Object> map)throws Exception {
		
		//封装tab
		Paged<StockCarVo> paged=new Paged<>();
		paged=getEncapsulationTab(paged);
		
		//获取仓库id参数
		getStockId(map);
		//获取参数
		Integer tabType = ObjectCastUtil.castInteger(map.get("tabType"));
		getParams(map,tabType);
		
		String vin = ObjectCastUtil.castString(map.get("vin"));
		String licencePlate = ObjectCastUtil.castString(map.get("licencePlate"));
		List<CarDto> carDtoList=null;
		if(StringUtils.isNoneBlank(vin) || StringUtils.isNoneBlank(licencePlate)) {
			CarsOperateStatusEnum statusEnum = null;
			carDtoList = carService.getCarListBySearch(vin, licencePlate, statusEnum);
			if(null == carDtoList || carDtoList.size() <=0 ) {
				return paged;
			}
		}
		/*封装车辆id*/
		if(null != carDtoList && carDtoList.size() > 0) {
			List<Integer> carIds=new ArrayList<>();
			for (CarDto carDto : carDtoList) {
				carIds.add(carDto.getId());
			}
			map.put("carIds", carIds);
		}
		
		Paged<StockCarBizDto> stockCarPaged = stockCarBizService.getStockCarList(map);
		if(null == stockCarPaged) {
			return paged;
		}else if(stockCarPaged.isEmpty()) {
			paged.setTotal(stockCarPaged.getTotal());
			paged.setPageSize(stockCarPaged.getPageSize());
			return paged;
		}
		List<StockCarBizDto> stockCarBizDtoList = stockCarPaged.getList();
		
		//获取车辆id集合
		List<Integer> carIds=new ArrayList<>();
		//获取车型id集合
		List<Integer> vehicleIds=new ArrayList<>();
		//获取车辆位置门店id集合
		List<Integer> storeIds=new ArrayList<>();
		//获取产权方id集合
		List<Integer> ownershipIds=new ArrayList<>();
		
		for (StockCarBizDto dto : stockCarBizDtoList) {
			carIds.add(dto.getCarId());
			vehicleIds.add(dto.getVehicleId());
			Integer stockTypeStore = dto.getStockType();
			if(null == stockTypeStore) {
				continue;
			}
			if(StockCarStockTypeEnum.STORE.getValue() == stockTypeStore) {
				storeIds.add(dto.getStoreId());
			}
		}
		//获取车辆信息
		Map<Integer, CarDto> carMap = carService.getCarByIds(carIds);
		if(null != carMap && !carMap.isEmpty()) {
			for (Integer key : carMap.keySet()) {
				CarDto carDto = carMap.get(key);
				if(null != carMap) {
					ownershipIds.add(carDto.getOwnershipId());
				}
			}
		}	
		//获取产权方信息
		Map<Integer, OwnershipDto> ownershipMap=null;
		if(!ownershipIds.isEmpty()) {
			ownershipMap= ownershipService.getOwnershipListByIds(ownershipIds);
		}	
		//获取车型信息
		Map<Integer, VehicleNameBizDto> vehicleNameMap= vehicleBizService.getCarByModelNameList(vehicleIds);
		//获取门店经销商信息
		Map<Integer, DealerStoreInfoBizDto> dealerMap =null;
		if(!storeIds.isEmpty()) {
			dealerMap= storeBizService.getDealerStoreInfoMap(storeIds);
		}
		
		//封装数据
		List<StockCarVo> stockCarVoList = getStockCarVoList(stockCarBizDtoList,carMap,ownershipMap,vehicleNameMap,dealerMap,tabType);
		paged.setList(stockCarVoList);
		paged.setPageSize(stockCarPaged.getPageSize());
		paged.setTotal(stockCarPaged.getTotal());
		return paged;
	}
	
	/**
	 * 获取库存车辆详情
	 * 
	 * @param carId
	 * @return
	 * @throws Exception 
	 */
	@Override
	public StockCarVo getStockCar(Integer carId) throws Exception {
		
		StockCarBizDto stockCar = stockCarBizService.getStockCar(carId);
		if(null == stockCar) {
			return null;
		}
		
		StockCarVo vo = Convert.toStockCarVo(stockCar);
		Integer storeId = stockCar.getStoreId();
		if(null != storeId) {
			DealerStoreInfoBizDto dealer= storeBizService.getDealerStoreInfo(storeId);
			if(null != dealer) {
				vo.setStockName(dealer.getDealerShortName()+"-"+dealer.getStoreShortName());
			}
		}
		
		
		CarDto car= carService.getCarById(carId);
		if(null != car ) {
			vo.setVin(car.getVin());
		}
		
		//查询车辆采购订单的经销商id
		OrderDealerDetailBasicDto dealer = orderDealerBizService.getDealerIdByCarId(carId);
		if(null != dealer) {
			vo.setDealerId(dealer.getDealerId());
		}
		
		return vo;
	}
	
	/**
	 * 获取库存车辆详情
	 * 
	 * @param carId
	 * @return
	 * @throws Exception 
	 */
	@Override
	public StockCarDetailVo getStockCarDetail(Integer carId) throws Exception {
		
		StockCarDetailDto stockCarDetail = stockCarBizService.getStockCarDetail(carId);
		if(null == stockCarDetail) {
			return null;
		}
		
		StockCarDetailVo vo = Convert.toStockCarDetailVo(stockCarDetail);
		
		Integer outStoreId = stockCarDetail.getOutStoreId();
		if(null != outStoreId) {
			DealerStoreInfoBizDto dealer= storeBizService.getDealerStoreInfo(outStoreId);
			if(null != dealer) {
				vo.setOutStockName(dealer.getDealerShortName()+"-"+dealer.getStoreShortName());
			}
		}
		
		CarDto car= carService.getCarById(carId);
		if(null != car ) {
			vo.setVin(car.getVin());
		}
		
		return vo;
	}
	
	/**
	 * 封装数据
	 * @param stockCarBizDtoList
	 * @param carMap
	 * @param ownershipMap
	 * @param vehicleNameMap
	 * @param dealerMap
	 * @param tabType
	 * @return
	 */
	private List<StockCarVo> getStockCarVoList(List<StockCarBizDto> stockCarBizDtoList,Map<Integer, CarDto> carMap,Map<Integer, OwnershipDto> ownershipMap,
			Map<Integer, VehicleNameBizDto> vehicleNameMap,Map<Integer, DealerStoreInfoBizDto> dealerMap,Integer tabType){
		List<StockCarVo> stockCarVoList=new ArrayList<>();
		stockCarBizDtoList.forEach(dto -> {
			
			StockCarVo vo = Convert.toStockCarVo(dto);
			//获取车辆信息
			CarDto carDto= null == carMap ? null : carMap.get(dto.getCarId());
			vo.setVin(carDto == null ? null : carDto.getVin());
			vo.setLicencePlate(carDto == null ? null : carDto.getLicencePlate());
			vo.setOwnershipId(carDto == null ? null : carDto.getOwnershipId());
			
			//获取车型信息
			VehicleNameBizDto vehicleNameBizDto= null == vehicleNameMap ? null : vehicleNameMap.get(dto.getVehicleId());
			vo.setVehicleName(vehicleNameBizDto== null ? null : 
				vehicleNameBizDto.getSubBrandName()+vehicleNameBizDto.getSeriesName()+vehicleNameBizDto.getModelName());
			vo.setVehicleImg(vehicleNameBizDto== null ? null : 
				vehicleNameBizDto.getWhiteFigure());
			
			//获取产权方信息
			OwnershipDto ownershipDto= null == ownershipMap ? null : ownershipMap.get(vo.getOwnershipId());
			vo.setOwnershipName(ownershipDto == null ? null : ownershipDto.getName());
			
			//获取车辆位置门店信息
			Integer stockType = dto.getStockType();
			Integer storeId = dto.getStoreId();
			if(null != stockType && null != storeId) {
				if(StockCarStockTypeEnum.STORE.getValue() == stockType) {
					DealerStoreInfoBizDto  storeDto = null == dealerMap ? null : dealerMap.get(storeId);
					vo.setStockName(storeDto == null ? null : storeDto.getDealerShortName()+"-"+storeDto.getStoreShortName());
				}
			}
			
			//获取枚举参数
			getParams(vo,tabType);
			vo.setTabTypeStr(StockStatusEnum.getName(tabType));
			stockCarVoList.add(vo);
		});
		return stockCarVoList;
	}
	
	/**
	 * 获取tab
	 * @param map
	 * @param paged
	 * @return
	 */
	private Paged<StockCarVo> getEncapsulationTab(Paged<StockCarVo> paged) {
		
		List<TabDto> tab=Arrays.asList(null,null,null,null);
		StockStatusEnum[] values = StockStatusEnum.values();
		Map<String, Object> map=new HashMap<>(2);
		for (StockStatusEnum stockStatusEnum : values) {
			TabDto tabDto=new TabDto();
			tabDto.setType(stockStatusEnum.getValue());
			tabDto.setName(stockStatusEnum.getName());
			
			//获取参数
			getParam(map,stockStatusEnum.getValue());
			
			Integer status=ObjectCastUtil.castInteger(map.get("status"));
			Integer inStockType=ObjectCastUtil.castInteger(map.get("inStockType"));
			
			Long count = stockCarService.getCount(status,inStockType);
			tabDto.setCount(count==null ? 0 :count.intValue());
			
			if(StockStatusEnum.YET_STOCK.getValue() == stockStatusEnum.getValue()) {
				tab.set(0, tabDto);
			}else if(StockStatusEnum.WAIT_STOCK.getValue() == stockStatusEnum.getValue()) {
				tab.set(1, tabDto);
			}else if(StockStatusEnum.YET_STORE.getValue() == stockStatusEnum.getValue()){
				tab.set(2, tabDto);
			}else {
				tab.set(3, tabDto);
			}
		}
		
		paged.setTab(tab);
		
        return paged;
	}
	
	/**
	 * 获取仓库id参数
	 * @param map
	 * @param tabType
	 */
	private void getStockId(Map<String, Object> map) {
		
		Integer stockType = ObjectCastUtil.castInteger(map.get("stockType"));
		Integer storeId = ObjectCastUtil.castInteger(map.get("stockId"));
		if(null != stockType && null != storeId) {
			if(StockCarStockTypeEnum.STORE.getValue() == stockType) {
				StockStoreDto stockStore = stockStoreService.getStockStoreByStoreId(storeId);
				map.put("stockId", stockStore == null ? null :stockStore.getStockId());
			}
		}
	 }
	
	/**
	 * 获取参数
	 * @param map
	 * @param tabType
	 */
	private void getParam(Map<String, Object> map,Integer tabType) {
		
		if(null == tabType) {
			map.put("status", StockCarStatusEnum.WAIT_STOCK.getValue());
			map.put("inStockType",StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue());
			return;
		}
		
		if(StockStatusEnum.WAIT_STOCK.getValue() == tabType) {
			map.put("status", StockCarStatusEnum.WAIT_STOCK.getValue());
			map.put("inStockType",StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue());
		}else if(StockStatusEnum.YET_STOCK.getValue() == tabType) {
			map.put("status",StockCarStatusEnum.YET_STOCK.getValue());
			map.put("inStockType",StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue());
			
		}else if(StockStatusEnum.WAIT_STORE.getValue() == tabType) {
			map.put("status",StockCarStatusEnum.WAIT_STOCK.getValue());
			map.put("inStockType",StockCarStockTypeEnum.STORE.getValue());
			
		}else if(StockStatusEnum.YET_STORE.getValue() == tabType) {
			map.put("status",StockCarStatusEnum.YET_STOCK.getValue());
			map.put("inStockType",StockCarStockTypeEnum.STORE.getValue());
			
		}else {
			map.put("status", StockCarStatusEnum.WAIT_STOCK.getValue());
			map.put("inStockType",StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue());
		}
	 }
	
	/**
	 * 获取参数
	 * @param map
	 * @param tabType
	 */
	private void getParams(Map<String, Object> map,Integer tabType) {
		
		if(null == tabType) {
			map.put("status", StockCarStatusEnum.WAIT_STOCK.getValue());
			map.put("inStockType",StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue());
			map.put("outStockId", map.get("stockId") == null ? null : map.get("stockId"));
			return;
		}
		
		if(StockStatusEnum.WAIT_STOCK.getValue() == tabType) {
			map.put("status", StockCarStatusEnum.WAIT_STOCK.getValue());
			map.put("inStockType",StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue());
			map.put("outStockId", map.get("stockId") == null ? null : map.get("stockId"));
			
		}else if(StockStatusEnum.YET_STOCK.getValue() == tabType) {
			map.put("status",StockCarStatusEnum.YET_STOCK.getValue());
			map.put("inStockType",StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue());
			map.put("inStockId", map.get("stockId") == null ? null : map.get("stockId"));
			
		}else if(StockStatusEnum.WAIT_STORE.getValue() == tabType) {
			map.put("status",StockCarStatusEnum.WAIT_STOCK.getValue());
			map.put("inStockType",StockCarStockTypeEnum.STORE.getValue());
			map.put("outStockId", map.get("stockId") == null ? null : map.get("stockId"));
			
		}else if(StockStatusEnum.YET_STORE.getValue() == tabType) {
			map.put("status",StockCarStatusEnum.YET_STOCK.getValue());
			map.put("inStockType",StockCarStockTypeEnum.STORE.getValue());
			map.put("inStockId", map.get("stockId") == null ? null : map.get("stockId"));
			
		}else {
			map.put("status", StockCarStatusEnum.WAIT_STOCK.getValue());
			map.put("inStockType",StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue());
			map.put("outStockId", map.get("stockId") == null ? null : map.get("stockId"));
		}
	 }
	
	/**
	 * 获取枚举参数
	 * 
	 * @param vo
	 * @param tabType
	 */
	private void getParams(StockCarVo vo,Integer tabType) {
		
		if(null != tabType && StockStatusEnum.WAIT_STORE.getValue() == tabType) {
			vo.setTypeStr(StockTypeEnum.ALLOT_IN_STORE.getName());
			return;
		}

		if (null == vo.getStockType()) {
			vo.setTypeStr(StockTypeEnum.PURCHASE_IN_STOCK.getName());
			return;
		}
		/* 中转库待入库 */
		if (StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue() == vo.getStockType()
				&& StockCarStatusEnum.WAIT_STOCK.getValue() == vo.getStatus()) {

			if (StockCarTypeEnum.PURCHASE.getValue() == vo.getType()) {

				vo.setTypeStr(StockTypeEnum.PURCHASE_IN_STOCK.getName());

			} else if (StockCarTypeEnum.ALLOT.getValue() == vo.getType()) {

				vo.setTypeStr(StockTypeEnum.ALLOT_OUT_STOCK.getName());

			} else if (StockCarTypeEnum.COLLECT.getValue() == vo.getType()) {

				vo.setTypeStr(StockTypeEnum.COLLECT_IN_STOCK.getName());
			}else if (StockCarTypeEnum.CAR_BACK.getValue() == vo.getType()) {

				vo.setTypeStr(StockTypeEnum.CAR_BACK_IN_STOCK.getName());
			}

			/* 中转库已入库 */
		} else if (StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue() == vo.getStockType()
				&& StockCarStatusEnum.YET_STOCK.getValue() == vo.getStatus()) {

			if (StockCarTypeEnum.PURCHASE.getValue() == vo.getType()) {

				vo.setTypeStr(StockTypeEnum.PURCHASE_IN_STOCK.getName());

			} else if (StockCarTypeEnum.ALLOT.getValue() == vo.getType()) {

				vo.setTypeStr(StockTypeEnum.ALLOT_IN_STOCK.getName());

			} else if (StockCarTypeEnum.REJECTION.getValue() == vo.getType()) {

				vo.setTypeStr(StockTypeEnum.REJECTION_IN_STOCK.getName());

			} else if (StockCarTypeEnum.COLLECT.getValue() == vo.getType()) {

				vo.setTypeStr(StockTypeEnum.COLLECT_IN_STOCK.getName());
			}else if (StockCarTypeEnum.CAR_BACK.getValue() == vo.getType()) {

				vo.setTypeStr(StockTypeEnum.CAR_BACK_IN_STOCK.getName());
			}

			/* 门店待入库 */
		} else {
			vo.setTypeStr(StockTypeEnum.ALLOT_IN_STORE.getName());
			if (StockCarTypeEnum.REJECTION.getValue() == vo.getType()) {

				vo.setTypeStr(StockTypeEnum.REJECTION_IN_STOCK.getName());

			} else if (StockCarTypeEnum.COLLECT.getValue() == vo.getType()) {

				vo.setTypeStr(StockTypeEnum.COLLECT_IN_STOCK.getName());
			}else if (StockCarTypeEnum.CAR_BACK.getValue() == vo.getType()) {

				vo.setTypeStr(StockTypeEnum.CAR_BACK_IN_STOCK.getName());
			}
		}
	}

	/**
	 * 车辆入库
	 * 
	 * @param modifyVo
	 * @return
	 * @throws Exception
	 */
	@Override
	public Boolean modifyInStock(StockCarModifyVo modifyVo) throws Exception {
		
		//验证参数
	    validateParams(modifyVo);
	    
	    StockCarDto stockCarDto = getStockCarDto(modifyVo.getCarId());
		if(modifyVo.getStockId().equals(stockCarDto.getOutStockId())) {
			throw new BizException(101,"车辆位置没有发生变化");
		}
		CarDto carDto = getCarDto(modifyVo.getCarId());
		
		//围栏验证
		getBindingFenceVerify( carDto, stockCarDto, modifyVo, "车辆已经绑定其它围栏");
		
		StockCarBizModifyDto modifyDto=new StockCarBizModifyDto();
		int stockType = StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue();
		BeanUtils.copyProperties(modifyVo, modifyDto);
		modifyDto.setStatus(StockCarStatusEnum.YET_STOCK.getValue());
		modifyDto.setStorageTime(DateUtil.convertDateToLDT(new Date()));
		modifyDto.setStockType(stockType);
		modifyDto.setAccountId(modifyVo.getOperateId());
		modifyDto.setAccountAccount(modifyVo.getOperateName());
		
		modifyStockIdById(modifyVo.getCarId(),modifyVo.getStockId(),stockType);
		
		if(carDto.getIsInstallTbox()) {
			//车辆绑定仓库围栏
			createBindingFence(modifyVo.getFenceId(),carDto.getVin());
		}
		return stockCarBizService.modifyInStock(modifyDto);
	}
	
	/**
	 * 围栏绑定
	 * @param fenceId
	 * @param vin
	 * @return
	 */
	private Boolean createBindingFence(Integer fenceId,String vin) {
		IovFenceBindingCreateDto dto = new IovFenceBindingCreateDto();
		if(null == fenceId || StringUtils.isAllBlank(vin)) {
			return false;
		}
		dto.setFenceId(Long.valueOf(fenceId));
		List<String> list= new ArrayList<>(1);
		list.add(vin);
		dto.setListVin(list);
		try {
			return iovFenceService.addBindingFence(dto);
		}catch (Exception e) {
			logger.error("围栏绑定异常：",e);
			return false;
		}
	}
	
	/**
	 * 解绑围栏
	 * @param fenceId
	 * @param vin
	 * @return
	 */
	private Boolean modifyBindingFence(Integer fenceId,String vin) {
		IovFenceBindingModifyDto  dto = new IovFenceBindingModifyDto();
		if(null == fenceId || StringUtils.isAllBlank(vin)) {
			return false;
		}
		dto.setFenceId(Long.valueOf(fenceId));
		List<String> list= new ArrayList<>(1);
		list.add(vin);
		dto.setListVin(list);
		try {
			return iovFenceService.modifyBindingFence(dto);
		}catch (Exception e) {
			logger.error("解绑围栏异常：",e);
			return false;
		}
	}
	
	/**
	 * 根据门店id 查询仓库id
	 * @param storeId
	 * @return
	 */
	private StockStoreDto getStockStoreByStoreId(Integer storeId) {
		//根据门店id 查询仓库id
		StockStoreDto stockStore = stockStoreService.getStockStoreByStoreId(storeId);
		if(null == stockStore ) {
			throw new BizException("门店信息没有仓库信息");
		}
		return stockStore;
	}
	
	/**
	 * 解除门店围栏 
	 * @param stockId
	 * @param vin
	 */
	private void modifyFenceStore(Integer stockId,String vin){
		StockStoreDto stockStore = getStockStore(stockId);
		StoreDetailDto store = getStoreDetailById(stockStore.getStoreId());
		Boolean flag = modifyBindingFence(store.getFenceId(), vin);
		if(!flag) {
			throw new BizException("车联网解除门店围栏失败!");
		}
	}
	
	/**解除仓库围栏 
	 * @param stockId
	 * @param vin
	 */
	private void modifyFenceStock(Integer stockId,String vin){
		EntrepotStorageDto entrepotStorage = getEntrepotStorage(stockId);
		Boolean flag = modifyBindingFence(entrepotStorage.getFenceId(), vin);
		if(!flag) {
			throw new BizException("车联网解除仓库围栏失败!");
		}
	}
	
	/**
	 * 车辆绑定仓库围栏
	 * @param stockId
	 * @param vin
	 */
	private void createFenceStock(Integer stockId,String vin) {
		EntrepotStorageDto entrepotStorage = getEntrepotStorage(stockId);
		Boolean flag = createBindingFence(entrepotStorage.getFenceId(),vin);
		if(!flag) {
			throw new BizException("车联网车辆绑定仓库围栏失败!");
		}
	}
	
	/**
	 * 车辆绑定门店围栏
	 * @param storeId
	 * @param vin
	 */
	private void createFenceStore(Integer storeId,String vin) {
		StoreDetailDto store = getStoreDetailById(storeId);
		Boolean flag = createBindingFence(store.getFenceId(),vin);
		if(!flag) {
			throw new BizException("车联网车辆绑定门店围栏失败!");
		}
	}
	
	/**
	 * 根据仓库id 查询门店id 
	 * @param stockId
	 * @return
	 */
	private StockStoreDto getStockStore(Integer stockId) {
		//根据仓库id 查询门店id
		StockStoreDto stockStore = stockStoreService.getStockStore(stockId);
		if(null == stockStore ) {
			throw new BizException("该仓库没有门店信息");
		}
		return stockStore;
	}
	
	/**
	 * 根据中转库id查询中转库信息
	 * @param stockId
	 * @return
	 */
	private EntrepotStorageDto getEntrepotStorage(Integer stockId) {
		EntrepotStorageDto entrepotStorage = entrepotStorageService.getEntrepotStorage(stockId);
		if(null == entrepotStorage) {
			throw new BizException("不存在该中转库信息");
		}
		return entrepotStorage;
	}
	
	/**
	 * 根据门店id获取门店信息
	 * @param storeId
	 * @return
	 */
	private StoreDetailDto getStoreDetailById(Integer storeId) {
		try {
			StoreDetailDto store = storeDetailService.getStoreDetailById(storeId);
			if(null == store) {
				throw new BizException("不存在该门店信息");
			}
			return store;
		} catch (Exception e) {
			logger.error("根据门店id获取门店信息异常：",e);
			throw new BizException("门店服务异常");
		}
	}
	
	/**
	 * 车辆出库
	 * 
	 * @param modifyVo
	 * @return
	 * @throws Exception
	 */
	@Override
	public Boolean modifyOutStock(StockCarModifyVo modifyVo) throws Exception {
		
		//验证参数
	    validateParams(modifyVo);
		
		StockCarBizModifyDto modifyDto=new StockCarBizModifyDto();
		BeanUtils.copyProperties(modifyVo, modifyDto);
		modifyDto.setStatus(StockCarStatusEnum.WAIT_STOCK.getValue());
		modifyDto.setStorageTime(DateUtil.convertDateToLDT(new Date()));
		modifyDto.setAccountId(modifyVo.getOperateId());
		modifyDto.setAccountAccount(modifyVo.getOperateName());
		modifyDto.setType(StockCarTypeEnum.ALLOT.getValue());
		
		StockCarDto stockCarDto = getStockCarDto(modifyVo.getCarId());
		//查询车辆采购订单的经销商id
		OrderDealerDetailBasicDto dealer= orderDealerBizService.getDealerIdByCarId(modifyVo.getCarId());
		if(null != dealer) {
			if(StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue() == modifyVo.getStockType()) {
				throw new BizException("该车辆只能出库到采购订单的门店下");
			}
		}
		
		boolean carIsLock = enterpriseCarService.getCarIsLock(modifyVo.getCarId());
		if(carIsLock) {
			throw new BizException("该车辆为锁定状态，不能调拨");
		}
		
		Integer carId = modifyDto.getCarId();
		CarDto carDto = getCarDto(carId);

		getModifyBindingFenceVerify(carDto,stockCarDto,"车辆未绑定仓储下的围栏");

		if(StockCarStockTypeEnum.STORE.getValue() == modifyVo.getStockType()) {
			
			if(!carDto.getIsInstallTbox()) {
				throw new BizException("未安装Tbox");
			}
			
			if(CarsOperateStatusEnum.FOR_RENT.getValue() != carDto.getStatus()) {
				throw new BizException("该车辆状态不是待出租状态");
			}
			
			DealerStoreInfoBizDto storeInfo = storeBizService.getDealerStoreInfo(modifyVo.getStockId());
			if(null == storeInfo || null == storeInfo.getStoreId()) {
				throw new BizException("不存在该门店信息");
			}
			
			//判断是否为该经销商下的门店
			if(null != dealer) {
				if(!dealer.getDealerId().equals(storeInfo.getDealerId())) {
					throw new BizException("该门店不是采购订单的门店");
				}
				if(!(OrderDealerStatusEnum.WAIT_DEPARTURE.getValue() == dealer.getOrderStatus()
						|| OrderDealerStatusEnum.WAIT_PICK_UP.getValue() == dealer.getOrderStatus())) {
					throw new BizException("订单状态不是等待发车状态");
				}
			}
			
			//根据门店id 查询仓库id
			StockStoreDto stockStore = getStockStoreByStoreId(modifyDto.getStockId());
			modifyDto.setStockId(stockStore.getStockId());
			
			//解除仓库围栏 
			modifyBindingFence(stockCarDto.getFenceId(),carDto.getVin());
			
			//如果为自销经销商 则 直接为 已入库状态
			if(DealerTypeEnum.DIRECT_SELL.getValue() == storeInfo.getDealerType()) {
				modifyDto.setStatus(StockCarStatusEnum.YET_STOCK.getValue());
				//围栏验证
				getBindingFenceVerify( carDto, stockCarDto, modifyVo, "车辆已经绑定其它围栏");
				
				modifyStockIdById(modifyVo.getCarId(),modifyDto.getStockId(),StockCarStockTypeEnum.STORE.getValue());
				//车辆绑定门店围栏
				createBindingFence(modifyVo.getFenceId(),carDto.getVin());
			}else {
				if(null == dealer || null == dealer.getId()) {
					throw new BizException(101,"车辆无采购订单只能发到直销经销商门店下");
				}
				//新增车辆的发车信息
				modifyCarStartStatus(storeInfo, modifyVo, stockCarDto);
			}
		}else {
			//解除仓库围栏 
			modifyBindingFence(stockCarDto.getFenceId(),carDto.getVin());
			
			if(modifyVo.getStockId().equals(stockCarDto.getInStockId())) {
				throw new BizException(101,"车辆位置没有发生变化");
			}
		}
		
		return stockCarBizService.modifyOutStock(modifyDto);
	}
	
	
	/**
	 * 验证围栏
	 * @param carDto
	 * @param stockCarDto
	 * @param exceptionStr
	 */
	private void getModifyBindingFenceVerify(CarDto carDto,StockCarDto stockCarDto,String exceptionStr) {
		Integer carId=carDto.getId();
		if(null == stockCarDto.getFenceId()) {
			 throw new BizException(101,"op车辆未绑定仓储下的围栏");
		}
		// 调取车联网接口 根据车辆VIN 获取围栏id
        List<String> vinList = new ArrayList<>(1);
        vinList.add(carDto.getVin());
        Map<String, List<IovFenceDto>> fenceMap = iovFenceService.getFenceByVins(vinList);

        //判断车联网接口返回围栏信息是否为空
        if(fenceMap == null || fenceMap.get(carDto.getVin()) == null || fenceMap.get(carDto.getVin()).size() <= 0){
            //新增异常 “车辆未绑定仓储下的围栏”
            FenceExceptionCreateDto fenceExceptionCreateDto = new FenceExceptionCreateDto();
            fenceExceptionCreateDto.setCarId(carId);
            fenceExceptionCreateDto.setFenceId(stockCarDto.getFenceId());
            fenceExceptionCreateDto.setStockId(carDto.getStockId());
			fenceExceptionCreateDto.setType(carDto.getStockType());
            fenceExceptionCreateDto.setExplain(exceptionStr);
            carFenceExceptionService.createCarFenceException(fenceExceptionCreateDto);
            throw new BizException(101,exceptionStr);
        }
        Integer iovFenceId = fenceMap.get(carDto.getVin()).get(0).getId();
        // 判断围栏id是否一致
        if(!iovFenceId.equals(stockCarDto.getFenceId())){
            //新增异常 “车辆绑定仓储与车辆绑定围栏不符”
            FenceExceptionCreateDto fenceExceptionCreateDto = new FenceExceptionCreateDto();
            fenceExceptionCreateDto.setCarId(carId);
            fenceExceptionCreateDto.setFenceId(stockCarDto.getFenceId());
            fenceExceptionCreateDto.setStockId(carDto.getStockId());
			fenceExceptionCreateDto.setType(carDto.getStockType());
            fenceExceptionCreateDto.setExplain("车辆绑定围栏与车联网不一致");
            carFenceExceptionService.createCarFenceException(fenceExceptionCreateDto);
            throw new BizException(101,"车辆绑定围栏与车联网不一致");
        }
	}
	
	/**
	 * 验证围栏
	 * @param carDto
	 * @param stockCarDto
	 * @param exceptionStr
	 */
	private void getBindingFenceVerify(CarDto carDto,StockCarDto stockCarDto,StockCarModifyVo modifyVo,String exceptionStr) {
		Integer carId=carDto.getId();
		// 调取车联网接口 根据车辆VIN 获取围栏id
        List<String> vinList = new ArrayList<>(1);
        vinList.add(carDto.getVin());
        Map<String, List<IovFenceDto>> fenceMap = iovFenceService.getFenceByVins(vinList);

        //判断车联网接口返回围栏信息是否为空
        if(fenceMap != null && fenceMap.get(carDto.getVin()) != null && fenceMap.get(carDto.getVin()).size() > 0){
            //新增车辆围栏异常 车辆已经绑定围栏
            FenceExceptionCreateDto fenceExceptionCreateDto = new FenceExceptionCreateDto();
            fenceExceptionCreateDto.setCarId(carId);
            fenceExceptionCreateDto.setFenceId(modifyVo.getFenceId());
            fenceExceptionCreateDto.setStockId(carDto.getStockId());
            fenceExceptionCreateDto.setExplain(exceptionStr);
            carFenceExceptionService.createCarFenceException(fenceExceptionCreateDto);
            throw new BizException(101,exceptionStr);
        }
        
	}
	
	/**
	 * 新增车辆的发车信息
	 * @param storeInfo
	 * @param modifyVo
	 * @return
	 * @throws Exception 
	 */
	private Boolean modifyCarStartStatus(DealerStoreInfoBizDto storeInfo,StockCarModifyVo modifyVo,StockCarDto stockCarDto) throws Exception {
		OrderDealerStartStatusModifyDto dto=new OrderDealerStartStatusModifyDto();
		dto.setCarId(modifyVo.getCarId());
		dto.setOperatorId(modifyVo.getOperateId());
		dto.setOperatorName(modifyVo.getOperateName());
		dto.setOperatorTime(DateUtil.convertDateToLDT(new Date()));
		dto.setTakeAite(storeInfo.getAddress());
		dto.setStoreId(modifyVo.getStockId());
		dto.setOutStockId(stockCarDto.getInStockId());
		return orderDealerBizService.modifyBizCarStartStatus(dto);
	}
	
	/**
	 * 确认回库
	 * 
	 * @param modifyVo
	 * @return
	 * @throws Exception
	 */
	@Override
	public Boolean modifyCollectStoreStock(StockCarModifyVo modifyVo) throws Exception {
		
		//验证参数
	    validateParams(modifyVo);
	    
	    StockCarDto stockCarDto = getStockCarDto(modifyVo.getCarId());
	   
	    if(modifyVo.getStockId().equals(stockCarDto.getOutStockId())) {
			throw new BizException(101,"车辆位置没有发生变化");
		}
	    
	    CarDto carDto = getCarDto(modifyVo.getCarId());
	    
	    //围栏验证
		getBindingFenceVerify( carDto, stockCarDto, modifyVo, "车辆已经绑定其它围栏");
	    
		StockCarBizModifyDto modifyDto=new StockCarBizModifyDto();
		BeanUtils.copyProperties(modifyVo, modifyDto);
		modifyDto.setStorageTime(DateUtil.convertDateToLDT(new Date()));
		modifyDto.setAccountId(modifyVo.getOperateId());
		modifyDto.setAccountAccount(modifyVo.getOperateName());
		
		/*查询采购订单号*/
		Long orderCode= orderDealerDeliveryService.getOrderCodeBycarId(modifyVo.getCarId());
		if(null != orderCode) {
			modifyDto.setOrderCode(orderCode);
			//解除车辆锁定状态
			orderDealerDeliveryService.modifyCarLock(modifyVo.getCarId());
		}
		
		modifyStockIdById(modifyVo.getCarId(),modifyVo.getStockId(),StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue());
		//车辆绑定仓库围栏
		createBindingFence(modifyVo.getFenceId(),carDto.getVin());
		
		return stockCarBizService.modifyCollectStoreStock(modifyDto);
	}
	
	/**
	 * 收车 车到中转库
	 * 
	 * @param modifyDto
	 * @return
	 */
	@Override
	public Boolean modifyCollectStock(StockCarModifyVo modifyVo) throws Exception {
		//验证参数
		validateParams(modifyVo);
		
		StockCarDto stockCarDto = getStockCarDto(modifyVo.getCarId());
		if(modifyVo.getStockId().equals(stockCarDto.getInStockId())) {
			throw new BizException(101,"车辆位置没有发生变化");
		}   
		
		CarDto carDto = getCarDto(modifyVo.getCarId());
		
		if(CarsOperateStatusEnum.FOR_RENT.getValue() != carDto.getStatus()) {
			throw new BizException("该车辆状态不是待出租状态");
		}
		getModifyBindingFenceVerify(carDto,stockCarDto,"车辆未绑定门店下的围栏");
		//解除门店围栏 
		modifyBindingFence(stockCarDto.getFenceId(),carDto.getVin());
		
		StockCarBizModifyDto modifyDto=new StockCarBizModifyDto();
		BeanUtils.copyProperties(modifyVo, modifyDto);
		modifyDto.setStorageTime(DateUtil.convertDateToLDT(new Date()));
		modifyDto.setAccountId(modifyVo.getOperateId());
		modifyDto.setAccountAccount(modifyVo.getOperateName());
		
		/*查询采购订单号*/
		Long orderCode= orderDealerDeliveryService.getOrderCodeBycarId(modifyVo.getCarId());
		if(null != orderCode) {
			modifyDto.setOrderCode(orderCode);
			//解除车辆锁定状态
			orderDealerDeliveryService.modifyCarLock(modifyVo.getCarId());
		}
		
		//围栏验证
		getBindingFenceVerify(carDto, stockCarDto, modifyVo, "车辆已经绑定其它围栏");
		
		modifyStockIdById(modifyVo.getCarId(),modifyVo.getStockId(),StockCarStockTypeEnum.ENTREPOT_STORAGE.getValue());
		//车辆绑定仓库围栏
		createBindingFence(modifyVo.getFenceId(),carDto.getVin());
		
		return stockCarBizService.modifyCollectStock(modifyDto);
	}
	
	/**
	 * 验证参数
	 * @param modifyVo
	 */
	private void validateParams(StockCarModifyVo modifyVo) {
		Assert.notNull(modifyVo,"参数不能为空");
		Assert.notNull(modifyVo.getCarId(), "carId不能为空");
		Assert.notNull(modifyVo.getStockId(), "stockId不能为空");
		Assert.notNull(modifyVo.getStockType(), "stockType不能为空");
		Assert.notNull(modifyVo.getFenceId(), "围栏id不能为空");
	}
	
	/**
	 * 获取车辆信息
	 * @param carId
	 * @return
	 */
    private CarDto getCarDto(Integer carId) {
    	CarDto carDto = carService.getCarById(carId);
		if(null == carDto) {
			throw new BizException("不存在该车辆信息");
		}
		return carDto;
    }
	
	/**
	 * 修改车辆所在位置
	 * @param carId
	 * @param stockId
	 * @param stockType
	 */
	private void modifyStockIdById(Integer carId, Integer stockId,  Integer stockType) {
		int num = carService.modifyStockIdById(carId,stockId,stockType);
		if(num != 1) {
		   throw new BizException(102, "车辆入库异常");
		}
	}
	
	/**
	 * 根据车辆id获取库存信息
	 * @param carId
	 * @return
	 */
	private StockCarDto getStockCarDto(Integer carId) {
		StockCarDto stockCarDto = stockCarService.getStockCar(carId);
		if(null == stockCarDto) {
			throw new BizException(101, "不存在该条信息");
		}
		return stockCarDto;
	}
	
	/**
	 * 获取库存车辆信息
	 * @param map
	 *            licencePlate(车牌) 
	 *            vin（车架号） 
	 *            vehicleId（车型）
	 *            vehicleType（车辆类型） 
	 *            status（运营状态）
	 * @return
	 * @throws Exception
	 */
	@Override
	public Paged<StockCarStockVo> getStockCarPage(Map<String, Object> map) throws Exception {
		Paged<StockCarStockVo> paged=new Paged<>();
		Paged<CarDto> stockCarPage = carService.getStockCarPage(map);
		paged.setTab(stockCarPage.getTab());
		if(stockCarPage.isEmpty()) {
			paged.setTotal(stockCarPage.getTotal());
			paged.setPageSize(stockCarPage.getPageSize());
			return paged;
		}
		List<CarDto> carDtoList = stockCarPage.getList();

		//获取车型id集合
		List<Integer> vehicleIds=new ArrayList<>();
		//获取车辆id集合
		List<Integer> carIds=new ArrayList<>();
		
        for (CarDto carDto : carDtoList) {
        	vehicleIds.add(carDto.getVehicleId());
        	carIds.add(carDto.getId());
		}
        Map<Integer, StockCarBizDto> stockBaseCarsMap = stockCarBizService.getStockBaseCars(carIds);
        //获取门店id集合
        List<Integer> storeIds= null;
        if(null != stockBaseCarsMap && !stockBaseCarsMap.isEmpty()) {
        	storeIds = getStoreIds(carIds,stockBaseCarsMap);
        }
        //获取门店经销商信息
      	Map<Integer, DealerStoreInfoBizDto> dealerMap =null;
      	if(null != storeIds && !storeIds.isEmpty()) {
      			dealerMap= storeBizService.getDealerStoreInfoMap(storeIds);
      	}
        //获取车型信息
        Map<Integer, VehicleNameBizDto> vehicleNameMap= vehicleBizService.getCarByModelNameList(vehicleIds);
        //封装数据
        List<StockCarStockVo> stockCarList = getStockCarPage(carDtoList,vehicleNameMap,dealerMap,stockBaseCarsMap);
    			
        paged.setList(stockCarList);
		paged.setPageSize(stockCarPage.getPageSize());
		paged.setTotal(stockCarPage.getTotal());
		return paged;
	}
	
	
	/**
	 * 封装数据
	 * @param carDtoList
	 * @param vehicleNameMap
	 * @param dealerMap
	 * @param stockBaseCarsMap
	 * @return
	 */
	private List<StockCarStockVo> getStockCarPage(List<CarDto> carDtoList,Map<Integer, VehicleNameBizDto> vehicleNameMap,
			Map<Integer, DealerStoreInfoBizDto> dealerMap,Map<Integer, StockCarBizDto> stockBaseCarsMap){
		List<StockCarStockVo> stockCarStockVo=new ArrayList<>();
		carDtoList.forEach(dto -> {
			StockCarStockVo vo = new StockCarStockVo();
			vo.setCarId(dto.getId());
			vo.setLicencePlate(dto.getLicencePlate());
			vo.setVin(dto.getVin());
            vo.setOperationState(dto.getStatus());	
            vo.setVehicleId(dto.getVehicleId());
			//获取车型信息
			VehicleNameBizDto vehicleNameBizDto= null == vehicleNameMap ? null : vehicleNameMap.get(dto.getVehicleId());
			vo.setVehicleName(vehicleNameBizDto== null ? null : 
				vehicleNameBizDto.getSubBrandName()+vehicleNameBizDto.getSeriesName()+vehicleNameBizDto.getModelName());
			vo.setVehicleImg(vehicleNameBizDto== null ? null : 
				vehicleNameBizDto.getWhiteFigure());
			
			
			//获取车辆位置信息
			Integer stockType = dto.getStockType();
			Integer stockId = dto.getStockId();
			if(null != stockType && null != stockId) {
				StockCarBizDto stockBaseDto = null == stockBaseCarsMap ? null : stockBaseCarsMap.get(dto.getId());
				if(StockCarStockTypeEnum.STORE.getValue() == stockType) {
					if(null != stockBaseDto && null != stockBaseDto.getStoreId()) {
						DealerStoreInfoBizDto  storeDto = null == dealerMap ? null : dealerMap.get(stockBaseDto.getStoreId());
						vo.setStockName(storeDto == null ? null : storeDto.getDealerShortName()+"-"+storeDto.getStoreShortName());
					}
				}else {
					vo.setStockName(stockBaseDto == null ? null : stockBaseDto.getStockName());
				}
			}
			stockCarStockVo.add(vo);
		});
		return stockCarStockVo;
	}
	
	/**
	 * 获取门店id
	 * @param carIds
	 * @param stockBaseCarsMap
	 * @return
	 */
	private List<Integer> getStoreIds(List<Integer> carIds,Map<Integer, StockCarBizDto> stockBaseCarsMap){
		//获取车辆位置门店id集合
		List<Integer> storeIds=new ArrayList<>();
		for (Integer carId : carIds) {
    		StockCarBizDto stockCarBizDto = stockBaseCarsMap.get(carId);
    		if(null != stockCarBizDto) {
    			Integer stockType = stockCarBizDto.getStockType();
    			if(null != stockType && StockCarStockTypeEnum.STORE.getValue() == stockType) {
    				storeIds.add(stockCarBizDto.getStoreId());
    			}
    		}
		}
		return storeIds;
	}
	
	/**
	 *库存车辆列表
	 * @param map 参数
	 *key:tabType        Integer    tab类型
	 *key:ids            List 	      库存id集合
	 *key:vin            String    车架号 非必填
	 *key:licencePlate   String    车牌号 非必填
	 *key:operationState Integer   运营状态 非必填
	 *key:vehicleId  Integer 车型id 非必填
	 *key:type       Integer 出入库类型 非必填
	 *key:stockType       Integer 库类型（中转库或门店）非必填
	 *key:stockId    Integer 中转库id 非必填
	 *key:startTime  LocalDateTime 开始时间 非必填
	 *key:endTime    LocalDateTime 结束时间 非必填
	 * @return
	 * @throws Exception 
	 */
	@Override
	public List<StockCarVo> getStockCarDownloadList(Map<String, Object> map) throws Exception {
		
		// 获取参数
		Integer tabType = ObjectCastUtil.castInteger(map.get("tabType"));
		getParams(map, tabType);
		if (null != map.get("ids") ) {
			map.put("ids", Arrays.asList(map.get("ids").toString().split(",")));
        	map.remove("carId");
        	map.remove("vehicleId");
        	map.remove("operationState");
        	map.remove("type");
        	map.remove("startTime");
        	map.remove("endTime");
        }else {
        	// 获取仓库id参数
    		getStockId(map);
    		String vin = ObjectCastUtil.castString(map.get("vin"));
    		String licencePlate = ObjectCastUtil.castString(map.get("licencePlate"));
    		if (StringUtils.isNoneBlank(vin) || StringUtils.isNoneBlank(licencePlate)) {
    		   CarDto carDto = carService.getByVinLicencePlate(vin,licencePlate);
    		   if(null == carDto || null == carDto.getId()) {
    			   return null;
    		   }
    		   map.put("carId", carDto.getId());
    		}
        }

		List<StockCarBizDto> stockCarBizDtoList = stockCarBizService.getStockCarDownloadList(map);
		if(null == stockCarBizDtoList || stockCarBizDtoList.isEmpty()) {
			return null;
		}
		// 获取车辆id集合
		List<Integer> carIds = new ArrayList<>();
		// 获取车型id集合
		Set<Integer> vehicleIdSets = new HashSet<>();
		// 获取车辆位置门店id集合
		Set<Integer> storeIdSets = new HashSet<>();
		// 获取产权方id集合
		Set<Integer> ownershipIdSets = new HashSet<>();

		for (StockCarBizDto dto : stockCarBizDtoList) {
			carIds.add(dto.getCarId());
			vehicleIdSets.add(dto.getVehicleId());
			Integer stockTypeStore = dto.getStockType();
			if (null == stockTypeStore) {
				continue;
			}
			if (StockCarStockTypeEnum.STORE.getValue() == stockTypeStore) {
				storeIdSets.add(dto.getStoreId());
			}
		}
		
		
		// 获取车型id集合
		List<Integer> vehicleIds = new ArrayList<>(vehicleIdSets);
		// 获取车辆位置门店id集合
		List<Integer> storeIds = new ArrayList<>(storeIdSets);
		
		// 获取车辆信息
		Map<Integer, CarDto> carMap = carService.getCarByIds(carIds);
		if (null != carMap && !carMap.isEmpty()) {
			for (Integer key : carMap.keySet()) {
				CarDto carDto = carMap.get(key);
				if (null != carMap) {
					ownershipIdSets.add(carDto.getOwnershipId());
				}
			}
		}
		
		// 获取产权方id集合
		List<Integer> ownershipIds = new ArrayList<>(ownershipIdSets);
		// 获取产权方信息
		Map<Integer, OwnershipDto> ownershipMap = null;
		if (!ownershipIds.isEmpty()) {
			ownershipMap = ownershipService.getOwnershipListByIds(ownershipIds);
		}
		// 获取车型信息
		Map<Integer, VehicleNameBizDto> vehicleNameMap = vehicleBizService.getCarByModelNameList(vehicleIds);
		// 获取门店经销商信息
		Map<Integer, DealerStoreInfoBizDto> dealerMap = null;
		if (!storeIds.isEmpty()) {
			dealerMap = storeBizService.getDealerStoreInfoMap(storeIds);
		}

		// 封装数据
		List<StockCarVo> stockCarVoList = getStockCarVoList(stockCarBizDtoList, carMap, ownershipMap, vehicleNameMap,
				dealerMap, tabType);
		return stockCarVoList;
	}
	
	@Override
	public Long getStockCarDownloadListCount(Map<String, Object> map) {
		// 获取参数
		Integer tabType = ObjectCastUtil.castInteger(map.get("tabType"));
		getParams(map, tabType);
		if (null != map.get("ids") ) {
			map.put("ids", Arrays.asList(map.get("ids").toString().split(",")));
        	map.remove("carId");
        	map.remove("vehicleId");
        	map.remove("operationState");
        	map.remove("type");
        	map.remove("startTime");
        	map.remove("endTime");
        }else {
        	// 获取仓库id参数
    		getStockId(map);
    		String vin = ObjectCastUtil.castString(map.get("vin"));
    		String licencePlate = ObjectCastUtil.castString(map.get("licencePlate"));
    		if (StringUtils.isNoneBlank(vin) || StringUtils.isNoneBlank(licencePlate)) {
    		   CarDto carDto = carService.getByVinLicencePlate(vin,licencePlate);
    		   if(null == carDto || null == carDto.getId()) {
    			   return null;
    		   }
    		   map.put("carId", carDto.getId());
    		}
        }	
		return stockCarService.getStockCarDownloadListCount(map);
	}
	
	@Async
	@Override
	public Boolean getStockCarDownloadListEmail(Map<String, Object> map,UserEntity user){
		try {
			List<StockCarVo> list = getStockCarDownloadList(map);
			String  fileName = "仓储作业列表(" + DateUtil.formatDate(LocalDate.now()) + ").xlsx";
			// 生成excel
			SXSSFWorkbook sxssBook = PoiExcelUtil.getStockCarDownloadList(list);
			// 发送邮件
			EmailUtil.sendMail(emailAccount, emailPassword, "仓储作业数据", "仓储作业数据", user.getAccount(), fileName, sxssBook);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return true;
	}
}
